<template>
  <div class="tag-table clearfix">
    <el-table
      :data="tableData"
      v-loading="loading"
      ref="tagTable"
      header-cell-class-name="header-cell-class"
      :cell-class-name="cellClass"
      :max-height="maxHeightNum"
      :height="height"
      stripe
      @sort-change="sortChange"
      :row-key="rowKey"
      @selection-change="selectChange"
      @expand-change="expandChange"
      @row-click="rowClick"
      @row-dblclick="rowDblclick"
      :default-expand-all="expandAll"
      :span-method="spanMethod"
    >
      <el-table-column
        v-if="selection"
        type="selection"
        width="50"
        reserve-selection
        align="center"
        :selectable="selectable"
      ></el-table-column>
      <el-table-column v-if="expand" type="expand">
        <template slot-scope="scope">
          <slot :scope="scope" name="expand"></slot>
        </template>
      </el-table-column>
      <el-table-column
        v-for="item in columnsShow"
        :label="item.label"
        :key="item.prop"
        :width="item.width"
        :min-width="item.minWidth"
        :align="item.align || 'left'"
        :header-align="item.headerAlign || 'center'"
        :show-overflow-tooltip="item.tooltip === false ? false : true"
        :prop="item.prop"
        :sortable="item.sort && !lockMode ? 'custom' : false"
      >
        <!-- 因后端技术实现问题，暂时取消多列搜索功能 -->
        <!-- <template slot="header" v-if="item.sort">
          <span>{{ item.label }}</span>
          <span class="sort-arrow-box">
            <i class="el-icon-caret-top" @click="sortUp(item.prop, $event)"></i>
            <i class="el-icon-caret-bottom" @click="sortDown(item.prop, $event)"></i>
          </span>
        </template> -->
        <template slot-scope="scope">
          <template v-if="scope.row.searchRow">
            <div v-if="item.search" class="table-search-class">
              <template v-if="!item.dict">
                <el-input
                  v-if="!item.searchType"
                  v-model="item.searchKey"
                  @keyup.enter.native="searchFun(item)"
                  @blur="searchFun(item)"
                  ><i slot="suffix" class="el-input__icon el-icon-close" @click="clearSearch(item)"></i
                ></el-input>
                <el-date-picker
                  v-else-if="item.searchType === 'dateTime'"
                  v-model="item.searchKey"
                  type="datetime"
                  placeholder="选择日期时间"
                  value-format="yyyy-MM-dd HH:mm:ss"
                  @change="timeChange(item)"
                >
                </el-date-picker>
                <el-date-picker
                  v-else-if="item.searchType === 'month'"
                  v-model="item.searchKey"
                  type="month"
                  placeholder="选择月份"
                  value-format="yyyy-MM"
                  @change="timeChange(item)"
                >
                </el-date-picker>
                <el-date-picker
                  v-else-if="item.searchType === 'daterange'"
                  type="daterange"
                  range-separator="至"
                  v-model="item.searchKey"
                  start-placeholder="开始日期"
                  end-placeholder="结束日期"
                  value-format="yyyy-MM-dd"
                  @change="dateChange(item)"
                ></el-date-picker>
                <el-select
                  v-else-if="item.searchType === 'select'"
                  v-model="item.searchKey"
                  @change="searchFun(item)"
                  :popper-class="pageClass"
                >
                  <el-option label="-" value=""></el-option>
                  <el-option
                    v-for="searchItem in item.searchList"
                    :key="searchItem.value"
                    :label="searchItem.key"
                    :value="searchItem.value"
                  ></el-option>
                </el-select>
              </template>
              <el-select v-else v-model="item.searchKey" @change="searchFun(item)" :popper-class="pageClass">
                <el-option label="-" value=""></el-option>
                <el-option
                  v-for="dict in $dictList(item.dict)"
                  :key="dict.key"
                  :label="dict.value"
                  :value="dict.key"
                ></el-option>
              </el-select>
            </div>
          </template>
          <slot v-else :scope="scope" :name="item.prop">
            <span
              v-if="item.dot && item.dot[scope.row[item.prop]]"
              class="cell-dot"
              :style="{ backgroundColor: item.dot[scope.row[item.prop]] }"
            ></span>
            <span v-if="item.dict">{{ getDictValue(scope.row[item.prop], item.dict) }}</span>
            <span v-else :class="{ 'cell-pre': item.tooltip === false }">{{ scope.row[item.prop] }}</span>
          </slot>
        </template>
      </el-table-column>
    </el-table>
    <el-pagination
      v-if="pagination && !lockMode"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page="params.currentPageNum"
      :page-sizes="pageSizes"
      :page-size="params.pageSize"
      background
      layout="total, prev, pager, next, jumper, sizes"
      :total="total"
      :popper-class="pageClass"
    >
    </el-pagination>
  </div>
</template>

<script>
export default {
  name: 'tag-table',
  props: {
    data: {
      type: Array,
      required: true,
      default: () => []
    },
    loading: {
      type: Boolean,
      default: false
    },
    columns: {
      type: Array,
      default: () => []
    },
    params: {
      type: Object,
      default: () => {
        return { ascs: [], descs: [], currentPageNum: 1, pageSize: 10, queryParams: {}, descPriority: false }
      }
    },
    pagination: {
      type: Boolean,
      default: true
    },
    pageSizes: {
      type: Array,
      default: () => [10, 15, 20, 30]
    },
    total: {
      type: Number,
      default: 0
    },
    maxHeight: {
      default: 'auto'
    },
    height: {
      default: undefined
    },
    selection: {
      type: Boolean,
      default: false
    },
    expand: {
      type: Boolean,
      default: false
    },
    expandAll: {
      type: Boolean,
      default: false
    },
    rowKey: {
      default: ''
    },
    pageClass: {
      default: ''
    },
    spanMethod: {
      type: Function
    }
  },
  data() {
    return {
      searchShow: false,
      searchList: [],
      selectList: [],
      lockMode: false
    }
  },
  computed: {
    tableData() {
      var data = []
      if (this.searchShow && !this.lockMode) {
        data.push({
          searchRow: true
        })
      }
      return data.concat(this.data)
    },
    columnsShow() {
      var arr = this.columns.filter(item => item.show)
      return arr
    },
    maxHeightNum() {
      if (this.maxHeight === 'auto' || this.pagination === false) {
        return this.maxHeight
      } else {
        return this.maxHeight - 42
      }
    }
  },
  watch: {
    searchList: {
      handler() {
        var query = {}
        this.searchList.forEach(item => {
          query[item.prop] = item.key
        })
        this.params.queryParams = query
        this.refreshData()
      },
      deep: true
    },
    total() {
      let maxPageNum = Math.ceil(this.total / this.params.pageSize) || 1
      if (this.params.currentPageNum > maxPageNum) {
        this.params.currentPageNum = maxPageNum
        this.refreshData()
      }
    }
  },
  methods: {
    cellClass({ row }) {
      if (row.searchRow) {
        return 'cell-search-class'
      } else {
        return 'cell-class'
      }
    },
    searchToggle(bool) {
      if (bool !== undefined) {
        this.searchShow = !!bool
      } else {
        this.searchShow = !this.searchShow
      }
    },
    searchFun(item) {
      var list = this.searchList
      if (item.searchKey.length === 0) {
        for (var i = 0; i < list.length; i++) {
          if (list[i].prop === item.prop) {
            list.splice(i, 1)
            break
          }
        }
      } else {
        var newParams = true
        for (var u = 0; u < list.length; u++) {
          if (list[u].prop === item.prop) {
            let key = item.searchKey
            if (item.searchType === 'daterange') {
              let v = []
              item.searchKey.forEach(value => v.push(value.replace(/-/g, '')))
              key = v.join('-')
            }
            list[u].key = key
            newParams = false
            break
          }
        }
        if (newParams) {
          let key = item.searchKey
          if (item.searchType === 'daterange') {
            let v = []
            item.searchKey.forEach(value => v.push(value.replace(/-/g, '')))
            key = v.join('-')
          }
          list.push({
            prop: item.prop,
            key: key,
            dict: item.dict
          })
        }
      }
    },
    clearSearch(item) {
      item.searchKey = ''
      this.searchFun(item)
    },
    clearAllSearch() {
      if (this.searchList.length !== 0) {
        for (var i = 0; i < this.columns.length; i++) {
          this.clearSearch(this.columns[i])
        }
      } else {
        this.refreshData()
      }
    },
    timeChange(item) {
      if (!item.searchKey) item.searchKey = ''
      this.searchFun(item)
    },
    dateChange(item) {
      if (!item.searchKey) item.searchKey = ''
      this.searchFun(item)
    },
    getDictValue(val, type) {
      if (typeof val === 'boolean') {
        val = val ? 1 : 0
      }
      return this.$dict(type)[val]
    },
    // 这里操作DOM是因为elementUI table的自定义表头有样式动态绑定会失效的BUG
    // 目前多列搜索功能暂时取消，以下两方法未使用
    sortUp(val, event) {
      var up = event.currentTarget
      var dowm = up.nextElementSibling
      var i = this.params.ascs.indexOf(val)
      if (i === -1) {
        this.params.ascs.push(val)
        up.classList.add('sort-select')
        var u = this.params.descs.indexOf(val)
        if (u !== -1) {
          this.params.descs.splice(u, 1)
          dowm.classList.remove('sort-select')
        }
      } else {
        this.params.ascs.splice(i, 1)
        up.classList.remove('sort-select')
      }
      this.refreshData()
    },
    sortDown(val, event) {
      var dowm = event.currentTarget
      var up = dowm.previousElementSibling
      var i = this.params.descs.indexOf(val)
      if (i === -1) {
        this.params.descs.push(val)
        dowm.classList.add('sort-select')
        var u = this.params.ascs.indexOf(val)
        if (u !== -1) {
          this.params.ascs.splice(u, 1)
          up.classList.remove('sort-select')
        }
      } else {
        this.params.descs.splice(i, 1)
        dowm.classList.remove('sort-select')
      }
      this.refreshData()
    },
    sortChange({ prop, order }) {
      if (order === 'ascending') {
        this.params.ascs = [prop]
        this.params.descs = []
      } else if (order === 'descending') {
        this.params.ascs = []
        this.params.descs = [prop]
      } else {
        this.params.ascs = []
        this.params.descs = []
      }
      this.refreshData()
    },
    refreshData() {
      this.$emit('refresh')
    },
    handleSizeChange(val) {
      this.params.currentPageNum = 1
      this.params.pageSize = val
      this.refreshData()
    },
    handleCurrentChange(val) {
      this.params.currentPageNum = val
      this.refreshData()
    },
    selectable(row) {
      return !row.searchRow
    },
    selectChange(val) {
      this.selectList = val
    },
    getSelectList() {
      return this.selectList
    },
    clearSelect() {
      this.$refs.tagTable.clearSelection()
    },
    lockToggle() {
      this.lockMode = !this.lockMode
    },
    expandChange(row, expandRows) {
      this.$emit('expandChange', { row, expandRows })
    },
    rowClick(row) {
      this.$emit('rowClick', row)
    },
    rowDblclick(row) {
      if (this.expand) this.$refs.tagTable.toggleRowExpansion(row)
    },
    refreshTable() {
      this.$refs.tagTable.doLayout()
    }
  }
}
</script>

<style lang="scss">
.tag-table {
  .el-table--enable-row-hover .el-table__body tr:hover > td {
    background-color: #ebf2f9;
  }
  .header-cell-class {
    padding: 0;
    color: #fff;
    font-weight: normal;
    background-color: #4d81ea;
    &:nth-last-child(2) {
      border-right: none;
    }
    .cell {
      font-size: 15px;
      line-height: 40px;
    }
    .caret-wrapper {
      position: absolute;
      top: 4px;
      right: 0;
    }
    &.is-leaf {
      border-bottom-color: #4d81ea;
    }
  }
  .gutter {
    background-color: #4d81ea;
  }
  .cell-class {
    padding: 8px 0;
    font-size: 14px;
  }
  .cell-dot {
    position: relative;
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    margin-right: 4px;
    &:before {
      content: '';
      position: absolute;
      top: 2px;
      left: 2px;
      width: 6px;
      height: 6px;
      border-radius: 50%;
      background-color: #fff;
    }
  }
  .cell-pre {
    white-space: pre-line;
  }
  .cell-search-class {
    text-align: center;
    padding: 4px 0;
    .table-search-class {
      max-width: calc(100% - 2px);
    }
    .el-input__inner {
      height: 30px;
      line-height: 30px;
      font-size: 13px;
    }
    .el-input__icon {
      line-height: 30px;
      cursor: pointer;
    }
    .el-select {
      width: 100%;
    }
  }
  .click-item {
    color: $theme-color;
    cursor: pointer;
  }
  .sort-arrow-box {
    position: absolute;
    top: 10px;
    right: 8px;
    font-size: 16px;
    color: #c0c4cc;
    width: 16px;
    cursor: pointer;
    .sort-select {
      color: #409eff;
    }
    i {
      float: left;
      line-height: 10px;
    }
  }
  .el-pagination {
    float: right;
    height: 32px;
    margin-top: 10px;
    padding-right: 20px;
    .el-pagination__sizes {
      margin: 0 0 0 14px;
    }
  }
  .el-date-editor.el-input,
  .el-date-editor.el-input__inner {
    width: 100%;
    .el-input__inner {
      padding-right: 0;
    }
    .el-input__suffix-inner {
      background-color: #fff;
    }
  }
  .typeIcon {
    color: $theme-color;
  }
  .cell-search-class .el-range-editor {
    .el-input__icon {
      line-height: normal;
    }
  }
  .el-range-separator {
    width: 30px;
    line-height: normal;
  }
}
</style>
